Skip to main content

Memory Allocation

package main

import "fmt"

var a = 10
var b = 20

func show(x int){
fmt.Println(x)
}

func add(x int, y int){
z := x + y
show(z)
}

func mul(x int){
z := x*a
fmt.Println(z)
}

func display(x int){
a := 100
mul(x)
fmt.Println(a)
}

func main(){
p := 30
q := 40
a := 40

add(p, q)
mul(q)

fmt.Print(a)
}

1. Memory placement

ItemSegment
show, add, mul, display, showCode segment
a, bData segment
Function locals & paramsStack

2. main() stack frame created

Stack:
| main() |
| p = 30 |
| q = 40 |
| a = 50 |

3. A new stack frame add() is pushed on top of main()

Stack:
| add(p, q) |
|-----------|
| main() |
| p = 30 |
| q = 40 |

Inside add():

Stack:
| add(p, q) |
| x = 30 |
| y = 40 |
| z = 70 |

4. Another stack frame is pushed on top of add()

Stack:
| show(z) |
|-----------|
| add(p, q) |
| z = 70 |
|-----------|
| main() |

Inside show()

Stack:
| show(z) |
| x = 70 |

70 is printed to stdout

5. show() frame destroyed

Stack:
| add(p, q) |
| z = 70 |
|-----------|
| main() |

6. add() frame destroyed

Stack:
| main() |
| p = 30 |
| q = 40 |

7. mul() frame is pushed on top of main()

| mul(q) |
|--------|
| main() |
| p = 30 |
| q = 40 |

Inside mul():

Stack:
| mul(q) |
| x = 40 |
| z = 40*10 |
  • mul() has no local a
  • main()’s a is NOT visible here
  • So Go uses the package-level a

A function can only see identifiers declared in its own scope or in enclosing (outer) scopes / lexical scope — never in a caller’s scope.

Scope hierarchy

Universe scope

Package scope

File scope

Function scope

Block scope

How name lookup works (algorithm)

When the compiler sees an identifier like a, it does this:

  1. Look in the current scope
  2. If not found, go to the immediate enclosing scope
  3. Repeat until:
    • Found → use it
    • Reach universe scope → error if still not found

Example lookup execution

  1. a isn't in block scope, theres nothing like ({ ... })
  2. a isn't in that function scope
  3. a isn't in the file scope
  4. a is in package scope

Caller scopes are never part of this lookup

8. Another stack frame is pushed on top of mul()

Stack:
| show(z) |
|----------|
| mul(q) |
| z = x*a |
|----------|
| main() |

9. mul() frame destroyed

10. main() frame popped

  • Runtime cleans up
  • Global memory released